package com.ybear.ybcomponent.widget.dialog.touch

import android.app.Activity
import android.view.MotionEvent
import android.view.View
import androidx.arch.core.util.Function
import androidx.fragment.app.Fragment
import com.ybear.ybcomponent.widget.dialog.DialogOption
import com.ybear.ybcomponent.widget.dialog.DialogX

/**
 * Dialog点击事件处理类
 */
open class DialogTouchEventHelper {
    private var mDialog: DialogX? = null
    private var decorViewX: Int = 0
    private var decorViewY: Int = 0
    private var widthByDecorView: Int = 0
    private var heightByDecorView: Int = 0

    open lateinit var dialogOption: DialogOption

    open fun initDialog(dialog: DialogX?) { mDialog = dialog }

    open fun initDecoViewSize(width: Int, height: Int) {
        widthByDecorView = width
        heightByDecorView = height
    }

    open fun initDecoViewLocation(decorViewX: Int, decorViewY: Int) {
        this.decorViewX = decorViewX
        this.decorViewY = decorViewY
    }

    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param activity          需要透传的Activity
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     * @param call              由于通过 setOnDispatchTouchEvent 实现透传，
     *                          所以该回调可以代替 setOnDispatchTouchEvent
     */
    open fun setOnTransferTouchEvent(activity: Activity?,
                                     authViewTransfer: Boolean,
                                     call: Function<MotionEvent, Boolean>?) : DialogOption {
        return dealOnTransferTouchEvent( authViewTransfer ) {
            val result = call?.apply( it ) ?: false
            if( activity == null || activity.isDestroyed ) {
                return@dealOnTransferTouchEvent result
            }
            return@dealOnTransferTouchEvent activity.dispatchTouchEvent( it )
        }
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param activity          需要透传的Activity
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     */
    open fun setOnTransferTouchEvent(activity: Activity?,
                                     authViewTransfer: Boolean) : DialogOption {
        return setOnTransferTouchEvent( activity, authViewTransfer, null )
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param activity          需要透传的Activity
     */
    open fun setOnTransferTouchEvent(activity: Activity?) : DialogOption {
        return setOnTransferTouchEvent( activity, false, null )
    }

    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param fragment          需要透传的Fragment
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     * @param call              由于通过 setOnDispatchTouchEvent 实现透传，
     *                          所以该回调可以代替 setOnDispatchTouchEvent
     */
    open fun setOnTransferTouchEvent(fragment: Fragment?, 
                                     authViewTransfer: Boolean, 
                                     call: Function<MotionEvent, Boolean>?) : DialogOption {
        return setOnTransferTouchEvent( fragment?.activity, authViewTransfer, call )
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param fragment          需要透传的Fragment
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     */
    open fun setOnTransferTouchEvent(fragment: Fragment?,
                                     authViewTransfer: Boolean) : DialogOption {
        return setOnTransferTouchEvent( fragment, authViewTransfer )
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param fragment          需要透传的Fragment
     */
    open fun setOnTransferTouchEvent(fragment: Fragment) : DialogOption {
        return setOnTransferTouchEvent( fragment, false, null )
    }
    
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param view              需要透传的View
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     * @param call              由于通过 setOnDispatchTouchEvent 实现透传，
     *                          所以该回调可以代替 setOnDispatchTouchEvent
     */
    open fun setOnTransferTouchEvent(view: View?,
                                     authViewTransfer: Boolean,
                                     call: Function<MotionEvent, Boolean>?) : DialogOption {
        return dealOnTransferTouchEvent( authViewTransfer ) {
            val result = call?.apply( it ) ?: false
            if( view == null ) return@dealOnTransferTouchEvent result
            return@dealOnTransferTouchEvent view.dispatchTouchEvent( it )
        }
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param view              需要透传的View
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     */
    open fun setOnTransferTouchEvent(view: View?,
                                     authViewTransfer: Boolean) : DialogOption {
        return setOnTransferTouchEvent( view, authViewTransfer, null )
    }
    /**
     * 设置透传点击事件（允许点击空白区域下层的控件）
     * @param view              需要透传的View
     */
    open fun setOnTransferTouchEvent(view: View?) : DialogOption {
        return setOnTransferTouchEvent( view, false, null )
    }

    /**
     * 处理透传点击事件（允许点击空白区域下层的控件）
     * @param authViewTransfer  允许在 decorView 控件范围内透传
     * @param call              返回处理
     */
    private fun dealOnTransferTouchEvent(authViewTransfer: Boolean,
                                         call: Function<MotionEvent, Boolean>) : DialogOption {
        return setOnDispatchTouchEvent {
            val x = it.x + decorViewX
            val y = it.y + decorViewY
            // 矫正实际位置
            it.setLocation( x, y )
            // 是否允许透传 decorView 控件
            if( !authViewTransfer ) {
                // 检查X坐标是否处于decorView范围内
                val checkX = x >= decorViewX && x <= decorViewX + widthByDecorView
                // 检查Y坐标是否处于decorView范围内
                val checkY = y >= decorViewY && y <= decorViewY + heightByDecorView
                // 处于decorView范围内时，不处理拦截
                if( checkX && checkY ) return@setOnDispatchTouchEvent true
            }
            return@setOnDispatchTouchEvent call.apply( it )
        }
    }

    /**
     * 点击事件拦截
     * * 如果使用了以下方法，则无需调用该方法，否则会覆盖
     *   setOnTransferTouchEvent
     */
    open fun setOnDispatchTouchEvent(call: Function<MotionEvent, Boolean>) : DialogOption {
        mDialog?.setOnDispatchTouchEvent( call )
        return dialogOption
    }
}